/*
//	wallpaper	hyt
//	winterborad
*/

//#define NO_SMS
#define NO_DEBUG
#define NO_LABEL
//#define NO_5DOCK

#import <UIKit/UIKit.h>
#include "substrate.h"

#ifndef NO_DEBUG
static void test(NSString *info)
{
	UIAlertView* __launchView = [[UIAlertView alloc] init];
	__launchView.title = @"Info";
	__launchView.message = info;
	[__launchView addButtonWithTitle:@"Dismiss"];
	[__launchView show];
	[__launchView release];
}
#define FILE_LOG ("/tmp/hyt.log")
void LOG(const char *fmt, ...)
{
	static	FILE	*fp	= NULL;

	va_list	ap;
	
	if(fp == NULL) {
        fp	= fopen(FILE_LOG, "a+");
        if(fp)
            fprintf(fp, "============================\n");
	}

	if(fp) {

        va_start(ap,fmt);

        vfprintf(fp,fmt,ap);
        fflush(fp);

        va_end(ap);
	}
}

#else
#define test 
#define LOG 
#endif


UIKIT_EXTERN NSString* UIKitDesktopImageChangedNotification;
UIKIT_EXTERN NSString* UIKitDockReflectionChangedNotification;
NSString* UIKitDockReflectionChangedNotification=@"com.apple.springboard.dock-reflection.changed";
static UIImageView* WPView_ = nil;
static UIView *SBButtonBar_ = nil;

static BOOL isWP_ = NO;
static BOOL isAB_ = NO;
static BOOL reflectionOn = NO;

static NSString* pID_=nil;
static NSString* WPPath_ = @"/var/mobile/Library/Wallpaper.jpg";
static NSString* msg_WP_[2] = {nil, nil};
static NSString* dockReflection_ = nil;


@interface NSObject(hyt)
+ (UIImage*)kitImageNamed:(NSString*)name;

- (void)setShowProgress:(BOOL)fp8 title:(id)fp12;
- (void)removeProgress;
- (void)setProgressDone;
- (void)setSeparatorColor:(id)color;
- (id)reflectedIcon:(BOOL)fp8;
- (BOOL)isInDock;
- (id)icons;

- (void)setContentView:(UIView*)fp8;
- (UIView*)contentView;

- (void)removeFileAtPath:(NSString*)fp8 handler:(id)fp12;

- (void)_setButtonType:(int)fp8;

- (void)insertSpecifier:(id)fp8 atEndOfGroup:(int)fp12;
//- (void)addSpecifiersFromArray:(id)fp8;
- (NSBundle*)bundle;

@end

@interface CQB : UIButton	{
	BOOL *_downRef;
	NSString* _path;
	NSString** _msg;
	CFAbsoluteTime  _mdt;
}
+ (id)buttonWithFrame:(CGRect)frame;
- (void)setDownRef:(BOOL*)downRef withImagePath:(NSString*)path withMsg:(NSString*[])msg;

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)removeDone;

@end

@implementation CQB
+ (id)buttonWithFrame:(CGRect)frame{
	CQB* button = [[[CQB alloc] initWithFrame:frame]autorelease];
	button.showsTouchWhenHighlighted = YES;
	[button setImage:[UIImage kitImageNamed:@"UIButtonBarInfo.png"] forState:UIControlStateNormal];	
	return button;
}
- (void)setDownRef:(BOOL*)downRef withImagePath:(NSString*)path withMsg:(NSString*[])msg{
	_downRef = downRef;		
	_path = path;
	_msg = msg;
}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
	_mdt = event.timestamp;
	[super touchesBegan:touches withEvent:event];
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
	if(![self isHighlighted])return;

	if(event.timestamp - _mdt > 1){
		[(self.superview.superview) setShowProgress:YES title:_msg[1]];
		[NSTimer scheduledTimerWithTimeInterval:0.3 target:self selector:@selector(removeDone) userInfo:nil repeats:NO];
		[[NSFileManager defaultManager]removeFileAtPath:_path handler:nil];//删除
		CFNotificationCenterPostNotification(CFNotificationCenterGetDarwinNotifyCenter(), (CFStringRef)UIKitDesktopImageChangedNotification, NULL, NULL, true);
		self.highlighted = NO;
	}
	else{
		*_downRef = YES;
		[super touchesEnded:touches withEvent:event];
		[(self.superview.superview) removeProgress];
		if(_msg[0]!=nil)
		[(self.superview.superview) setShowProgress:YES title:_msg[0]];
	}
}
- (void)removeDone{
	[self.superview.superview setProgressDone];
	[NSTimer scheduledTimerWithTimeInterval:0.3 target:(self.superview.superview) selector:@selector(removeProgress) userInfo:nil repeats:NO];
}

@end

MSHook(id, SBUIController$init, id self, SEL sel) {
    self = _SBUIController$init(self, sel);

	UIView *contentView = [[self window] contentView];
    [contentView setBackgroundColor:[UIColor clearColor]];
    UIView *content([[[UIView alloc] initWithFrame:[contentView frame]] autorelease]);
    [content setBackgroundColor:[UIColor clearColor]];
    [contentView setFrame:[content bounds]];
    [[self window] setContentView:content];

	WPView_ = [[[UIImageView alloc] initWithFrame:[contentView frame]]autorelease];
	WPView_.backgroundColor = [UIColor clearColor];

	[content addSubview:WPView_];
	[content addSubview:contentView];

	WPView_.image = [UIImage imageWithContentsOfFile:WPPath_];
	
	UIView *&_buttonBarContainerView(MSHookIvar<UIView *>(self, "_buttonBarContainerView"));
	_buttonBarContainerView.backgroundColor = [UIColor clearColor];
	
	SBButtonBar_ = [_buttonBarContainerView.subviews objectAtIndex:0];
	
	return self;
}

MSHook(void, SBStatusBarContentsView$didMoveToSuperview, UIView *self, SEL sel) {
    [[self superview] setBackgroundColor:[UIColor clearColor]];
    _SBStatusBarContentsView$didMoveToSuperview(self, sel);
}

MSHook(id, SBSearchView$initWithFrame$, UIView *self, SEL sel, CGRect frame) {
    if ((self = _SBSearchView$initWithFrame$(self, sel, frame)) != nil) {
        [self setBackgroundColor:[UIColor clearColor]];
        for (UIView *child in [self subviews])
            [child setBackgroundColor:[UIColor clearColor]];
    } return self;
}

#ifndef NO_5DOCK
MSHook(int, SBButtonBar$maxIconColumns, UIView* self, SEL sel) {
	return 5;
}

static unsigned $SBButtonBar$count(UIView* self) {
    NSArray *&_iconMatrix(MSHookIvar<NSArray *>(self, "_iconMatrix"));
    NSArray *row([_iconMatrix objectAtIndex:0]);
    unsigned count(0);
    for (id icon in row)
        if (icon != [NSNull null])
            ++count;
    return count;
}

MSHook(float, SBButtonBar$topIconPadding, UIView* self, SEL sel) {
	return $SBButtonBar$count(self);
}

MSHook(CGPoint, SBButtonBar$originForIconAtX$Y$, id self, SEL sel, int x, int y) {
    CGPoint origin;
    origin.y = 11;

    unsigned count($SBButtonBar$count(self)), gap;
    unsigned space(320 - 60 * count);

    if (count >= 4)
        gap = space / (count + 1);
    else
        gap = 16;

    origin.x = (space - gap * (count - 1)) / 2 + (60 + gap) * x;

    return origin;
}

MSHook(void, SBIcon$setOrigin$, id self, SEL sel, CGPoint origin) {
    unsigned count(origin.y);

    if (count < 45 && count > 40)
        origin.x = 256;
    else if (count > 10 || count < 0)
        goto set;
    else if (count == 5)
        origin.x = (origin.x - 4) / 76 * 63 + 4;

    origin.y = 11;
  set:
	_SBIcon$setOrigin$(self, sel, origin);
}
#endif //NO_5DOCK

MSHook(void, SBIcon$setInDock$, UIView *self, SEL sel, BOOL unknown) {
	static CGAffineTransform CGReflection = CGAffineTransformMake(1, 0, 0, -1, 0, 0);

	UIImageView *_reflection = (UIImageView*)[self viewWithTag:101];
	if(unknown){
		if(_reflection==nil){
			UIImage *reflection = [self reflectedIcon:NO];
			if(reflection){
				UIImageView *mm_reflection = [[UIImageView alloc]initWithImage:reflection];
				static CGPoint CGCenter = CGPointMake(mm_reflection.center.x, mm_reflection.center.y+55);
				mm_reflection.center = CGCenter;
				mm_reflection.tag = 101;
				mm_reflection.transform = CGReflection;
				mm_reflection.hidden = !reflectionOn;
				[self addSubview: mm_reflection];
				[mm_reflection release];
			}
		}else{_reflection.hidden = !reflectionOn;}
	}
	else if(_reflection!=nil){
		_reflection.hidden = YES;
	}

	_SBIcon$setInDock$(self, sel, unknown);

}

#ifndef NO_LABEL

static NSString* const styleB_ = @"font-family: Helvetica; "
        "font-weight: bold; "
        "font-size: %dpx; "
		"color: rgb(255, 255, 255); "
		"text-align: center; "
		"text-shadow: rgb(0,0,0) 0px 0px 2px; "
		"width: %dpx; "
		"letter-spacing: -0.3px; "
		"word-spacing: -1.5px; "
		"white-space: nowrap; "
		"overflow: hidden; "
		"float: left; "
		"text-overflow: ellipsis; ";

@interface NSString(hyt)
- (void) drawInRect:(CGRect)bounds withStyle:(NSString*)style;
@end
MSHook(void, SBIconLabel$drawRect$, UIControl *self, SEL sel, CGRect rect) {
	NSString *&label(MSHookIvar<NSString *>(self, "_label"));
	const char * str =  [label UTF8String];
	bool isChinese = false;
	while(*str!='\0'){
		if(*str<0){
			isChinese = true;	break;
		}	str++;
	}

    CGRect bounds = CGRectInset([self bounds], -3, 0);
	NSString *style = [NSString stringWithFormat:styleB_, isChinese ? 12 : 11, (int)bounds.size.width];

	[label drawInRect:bounds withStyle:style];
}
#endif

#ifndef NO_SMS

static BOOL isSMS_ = NO;
static NSString *SMSPath_ = @"/var/mobile/Library/SMSBackground.jpg";
static NSString* msg_SMS_[2] = {nil, nil};
static UIImageView *background = nil;

@interface UIViewController(hyt)
- (UITableView*)transcriptTable;
@end

static void FF(UIInterfaceOrientation toInterfaceOrientation){
	static CGAffineTransform transform1 = CGAffineTransformTranslate(CGAffineTransformMakeRotation(M_PI/2), -132, -80);
	static CGAffineTransform transform2 = CGAffineTransformMakeTranslation(0, -65);

	if(UIInterfaceOrientationIsLandscape(toInterfaceOrientation) && background!=nil)//横向
		background.transform = transform1;
	else
		background.transform = transform2;
}

MSHook(void, CKTranscriptController$_reloadTranscriptLayer, UIViewController* self, SEL sel) {
	_CKTranscriptController$_reloadTranscriptLayer(self, sel);
	FF(self.interfaceOrientation);
}

MSHook(void, CKTranscriptController$loadView, UIViewController* self, SEL sel) {
    _CKTranscriptController$loadView(self, sel);
	UIImage *image = [UIImage imageWithContentsOfFile:SMSPath_];
	if (image != nil) {
		UITableView *_transcriptTable([self transcriptTable]);
		background = [[[UIImageView alloc] initWithImage:image] autorelease];
		[[_transcriptTable superview] insertSubview:background belowSubview:_transcriptTable];
		_transcriptTable.backgroundColor = [UIColor clearColor];
		_transcriptTable.separatorStyle = UITableViewCellSeparatorStyleNone;
		FF(self.interfaceOrientation);
	}
}

MSHook(void, CKTranscriptController$willRotateToInterfaceOrientation$duration$, id self, SEL sel, UIInterfaceOrientation toInterfaceOrientation, NSTimeInterval duration) {
	_CKTranscriptController$willRotateToInterfaceOrientation$duration$(self, sel, toInterfaceOrientation, duration);
	FF(toInterfaceOrientation);
}

MSHook(void, CKMessageCell$addBalloonView$, id self, SEL sel, id ballon) {
    _CKMessageCell$addBalloonView$(self, sel, ballon);
	[[self contentView] setBackgroundColor:[UIColor clearColor]];
	[[self selectedBackgroundView] setBackgroundColor:[UIColor clearColor]];
	[ballon setBackgroundColor:[UIColor clearColor]];
}

MSHook(UIColor*, CKMessageCell$_multiselectBackgroundColor, id self, SEL sel) {
	return [UIColor clearColor];
}

MSHook(void, CKTimestampView$setDate$, id self, SEL sel, id date) {
	UILabel *&_label(MSHookIvar<UILabel *>(self, "_label"));
	[_label setBackgroundColor:[UIColor clearColor]];
	_CKTimestampView$setDate$(self, sel, date);
}
#endif //NO_SMS


MSHook(void, PLAlbumsController$assignToContactClicked, id self, SEL sel) {
	isAB_ = YES;
	_PLAlbumsController$assignToContactClicked(self, sel);
}

static UIView * HiddenBtn(UIView *self, BOOL hidden){
	UIView *&_lcd(MSHookIvar<UIView *>(self, "_lcd"));
	if([_lcd.subviews count] >= 2)
	{
		for(UIView *btn in _lcd.subviews)
			btn.hidden = hidden;
	}
	return _lcd;
}

MSHook(void, PLCropOverlay$cancelButtonClicked$, UIView *self, SEL sel, id sender) {
	_PLCropOverlay$cancelButtonClicked$(self, sel, sender);
	isAB_ = NO;
	HiddenBtn(self, YES);
}

MSHook(void, PLCropOverlay$okButtonClicked$, UIView *self, SEL sel, id sender) {
	_PLCropOverlay$okButtonClicked$(self, sel, sender);
	isAB_ = NO;
	HiddenBtn(self, YES);
}

MSHook(void, PLCropOverlay$setTitle$okButtonTitle$, UIView *self, SEL sel, NSString * title, id okButtonTitle) {
    _PLCropOverlay$setTitle$okButtonTitle$(self, sel, title, okButtonTitle);

	if(isAB_)return;

	UIView *_lcd = HiddenBtn(self, NO);
	
	CQB *_wpButton = [CQB buttonWithFrame:CGRectMake(280, 35, 21, 21)];
	[_wpButton setDownRef:(&isWP_) withImagePath:WPPath_ withMsg:msg_WP_];
	[_wpButton addTarget:self action:@selector(okButtonClicked:) forControlEvents:UIControlEventTouchUpInside];
	[_lcd addSubview:_wpButton];

#ifndef NO_SMS
	CQB *_smsButton = [CQB buttonWithFrame:CGRectMake(20, 35, 21, 21)];
	[_smsButton setDownRef:(&isSMS_) withImagePath:SMSPath_ withMsg:msg_SMS_];
	[_smsButton addTarget:self action:@selector(okButtonClicked:) forControlEvents:UIControlEventTouchUpInside];
	[_lcd addSubview:_smsButton];
#endif //NO_SMS
}

MSHook(id, PLCropOverlay$hitTest$withEvent$, UIView *self, SEL sel, CGPoint point, id event) {
	if(!isAB_){
		UIView *&_lcd(MSHookIvar<UIView *>(self, "_lcd"));

		CQB *_Button = [_lcd.subviews objectAtIndex:0];
		if (CGRectContainsPoint(CGRectInset(_Button.frame,-2,-3), [self convertPoint:point toView:_lcd])) {return _Button;}

	#ifndef NO_SMS
		_Button = [_lcd.subviews objectAtIndex:1];
		if (CGRectContainsPoint(CGRectInset(_Button.frame,-2,-3), [self convertPoint:point toView:_lcd])) {return _Button;}
	#endif
	}
	return _PLCropOverlay$hitTest$withEvent$(self, sel, point, event);
}

MSHook(void, NSData$writeToFile$atomically$, NSData *self, SEL sel, NSString *path, BOOL useAuxiliaryFile){
	if(isWP_) {isWP_ = NO;	path = WPPath_;}
#ifndef NO_SMS
	else if(isSMS_)	{isSMS_ = NO;	path = SMSPath_;}
#endif //NO_SMS
	_NSData$writeToFile$atomically$(self, sel, path, useAuxiliaryFile);
}

@class PSSpecifier;
@class PSListController;
UIKIT_EXTERN NSMutableArray* SpecifiersFromPlist (
							  NSDictionary*     plist,      // r0
							  PSSpecifier*      specifier,  // r1
							  id                target,     // r2
							  NSString*         plistName,  // r3
							  NSBundle*         curBundle,           // sp[0x124]
							  NSString**        pTitle,              // sp[0x128]
							  NSString**        pSpecifierID,        // sp[0x12C]
							  PSListController* callerList,          // sp[0x130]
							  NSMutableArray**  pBundleControllers   // sp[0x134]
);

#define SpecifiersFromPlistOnSelf(plist) SpecifiersFromPlist([NSDictionary dictionaryWithObject:(plist) forKey:@"items"], nil, self, nil, [self bundle], NULL, NULL, self, NULL)


MSHook(NSArray*, PrefsListController$specifiers, id self, SEL sel) {
    NSArray *&_specifiers(MSHookIvar<NSArray *>(self, "_specifiers"));
	if(_specifiers == nil){
		_PrefsListController$specifiers(self, sel);

		NSMutableArray* specPlist = [NSMutableArray arrayWithObject:
						[NSDictionary dictionaryWithObjectsAndKeys:
							UIKitDockReflectionChangedNotification, @"PostNotification",
							@"PSSwitchCell", @"cell",
							@"true", @"default",
							@"com.dock.reflection", @"defaults",
							@"/Library/MobileSubstrate/wallpaper/icon.png", @"icon",
							@"reflectionOn", @"key",
							dockReflection_, @"label",
							nil
							]];
		NSArray *specPlist_ = SpecifiersFromPlistOnSelf(specPlist);
		[self insertSpecifier:[specPlist_ objectAtIndex:0] atEndOfGroup:1];
	}
	return _specifiers;
}

static void ChangeWallpaper(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef info) {
    if (WPView_ != nil)	[WPView_ setImage:[UIImage imageWithContentsOfFile:WPPath_]];
}

static void ChangeDockReflection(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef info) {
	if(SBButtonBar_!=nil){
		reflectionOn = !reflectionOn;
		for (UIView* icon in [SBButtonBar_ icons])
			if (icon != nil){
				UIImageView *_reflection = (UIImageView*)[icon viewWithTag:101];
				if(_reflection)
					_reflection.hidden = !reflectionOn;
			}
	}		
}

#define WPRename(name, sel, imp) \
    _ ## name ## $ ## imp = MSHookMessage($ ## name, @selector(sel), &$ ## name ## $ ## imp)

extern "C" void WPInitialize() {
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

    pID_ = [[NSBundle mainBundle] bundleIdentifier];

	if ([pID_ isEqualToString:@"com.apple.springboard"]) {
		CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(),
			NULL, &ChangeWallpaper, (CFStringRef)UIKitDesktopImageChangedNotification, NULL, CFNotificationSuspensionBehaviorHold);
		CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(),
			NULL, &ChangeDockReflection, (CFStringRef)UIKitDockReflectionChangedNotification, NULL, CFNotificationSuspensionBehaviorHold);
		
		Class $SBIcon = objc_getClass("SBIcon");
		Class $SBSearchView = objc_getClass("SBSearchView");
		Class $SBUIController = objc_getClass("SBUIController");
		Class $SBStatusBarContentsView = objc_getClass("SBStatusBarContentsView");

		WPRename(SBUIController, init, init);
		WPRename(SBSearchView, initWithFrame:, initWithFrame$);
		WPRename(SBStatusBarContentsView, didMoveToSuperview, didMoveToSuperview);

		WPRename(SBIcon, setInDock:, setInDock$);
#ifndef NO_5DOCK
		WPRename(SBIcon, setOrigin:, setOrigin$);

		Class $SBButtonBar = objc_getClass("SBButtonBar");
		WPRename(SBButtonBar, maxIconColumns, maxIconColumns);
		WPRename(SBButtonBar, topIconPadding, topIconPadding);
		WPRename(SBButtonBar, originForIconAtX:Y:, originForIconAtX$Y$);
#endif //NO_5DOCK

#ifndef NO_LABEL
		Class $SBIconLabel = objc_getClass("SBIconLabel");
		WPRename(SBIconLabel, drawRect:, drawRect$);
#endif //NO_LABEL

		NSString *plist = [NSString stringWithFormat:@"%@/Library/Preferences/com.dock.reflection.plist", NSHomeDirectory()];
		NSMutableDictionary *settings = [[NSMutableDictionary alloc] initWithContentsOfFile:plist];
		if (settings != nil){
			reflectionOn = [[settings objectForKey:@"reflectionOn"] boolValue];
		}

	}
	else if ([pID_ isEqualToString:@"com.apple.Preferences"] || [pID_ isEqualToString:@"com.apple.mobileslideshow"]) {

		NSBundle *bundle = [[NSBundle alloc] initWithPath:@"/Library/MobileSubstrate/wallpaper"];
		dockReflection_ = [bundle localizedStringForKey:@"DOCK_REFLECTION" value:@"" table:nil];
		msg_WP_[0] = [bundle localizedStringForKey:@"SET_WALLPAPER" value:@"" table:nil];
		msg_WP_[1] = [bundle localizedStringForKey:@"DELETE_WALLPAPER" value:@"" table:nil];
#ifndef NO_SMS
		msg_SMS_[0] = [bundle localizedStringForKey:@"SET_SMSBG" value:@"" table:nil];
		msg_SMS_[1] = [bundle localizedStringForKey:@"DELETE_SMSBG" value:@"" table:nil];	
#endif //NO_SMS
		[bundle release];

		Class $PLCropOverlay = objc_getClass("PLCropOverlay");

		WPRename(PLCropOverlay, setTitle:okButtonTitle:, setTitle$okButtonTitle$);
		WPRename(PLCropOverlay, hitTest:withEvent:, hitTest$withEvent$);
		WPRename(PLCropOverlay, cancelButtonClicked:, cancelButtonClicked$);
		WPRename(PLCropOverlay, okButtonClicked:, okButtonClicked$);

		Class $NSData = objc_getClass("NSData");
		WPRename(NSData, writeToFile:atomically:, writeToFile$atomically$);

		if([pID_ isEqualToString:@"com.apple.mobileslideshow"]){
			Class $PLAlbumsController =  objc_getClass("PLAlbumsController");
			WPRename(PLAlbumsController, assignToContactClicked, assignToContactClicked);
		}
		else{
			Class $PrefsListController = objc_getClass("PrefsListController");
			WPRename(PrefsListController, specifiers, specifiers);
		}
	}
#ifndef NO_SMS
	else if ([pID_ isEqualToString:@"com.apple.MobileSMS"]) {
		Class $CKTranscriptController =  objc_getClass("CKTranscriptController");
		Class $CKMessageCell =  objc_getClass("CKMessageCell");
		Class $CKTimestampView =  objc_getClass("CKTimestampView");

		WPRename(CKTimestampView, setDate:, setDate$);
		WPRename(CKMessageCell, addBalloonView:, addBalloonView$);
		WPRename(CKMessageCell, _multiselectBackgroundColor, _multiselectBackgroundColor);
		WPRename(CKTranscriptController, loadView, loadView);
		WPRename(CKTranscriptController, _reloadTranscriptLayer, _reloadTranscriptLayer);
		WPRename(CKTranscriptController, willRotateToInterfaceOrientation:duration:, willRotateToInterfaceOrientation$duration$);
    }
#endif //NO_SMS

	[pool release];
}
